﻿
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using Random = UnityEngine.Random;
using System.Reflection;
using System.Linq;

public class PaperManager : MonoSingleton<PaperManager>
{

    public string assetdir;
    const string cardbundleName = "card";

    public enum AssetType
    {
        MediaAssets,
        AssetBundle,//资源包中包含图片和自定义shader资源
        SuperAssetBundle, //资源包中包含卡片脚本在内的所以资源
        Spine       //Spine动画
    }

    public enum Catagory
    {
        Other,
        Human,
        Nature
    }

    //鼠标检测模式（检测鼠标是否滑入）
    public enum CheckMode
    {
        None,
        WindowArea,
        Accurate,
        HighAccurate
    }

    //卡片类型
    public enum CardType
    {
        SimpleCard,
        SimpleGifCard,
        AcurrateCollisionCard,
        SimpleSpineCard
    }

    //图片或视频切换的模式
    public enum ItemChangeMode
    {
        Sequence,
        Random,
        Stanby,
        Max
    }

    //淡入方式
    public enum FadeInType
    {
        SimpleAlphaFade,
        SimpleFlyIn,
        SimpleSpriteIn,
        Random,
        Max
    }

    //淡出方式
    public enum FadeOutType
    {
        SimpleAlphaFade,
        SimpleFlyOut,
        SimpleSpriteOut,
        Random,
        Max
    }

    float changedur = 20f;
    float timer = 0;

    List<string> shower_items = new List<string>();
    AssetBundle currentAssetbundle;
    int current_shower_index;
    PackageData appConfigData;
    ItemChangeMode changeMode;
    CardType cardtype;

    Transform anchor1, anchor2;

    void Start()
    {

        anchor1 = transform.Find("anchor1");
        anchor2 = transform.Find("anchor2");
        OnPackageChange();
    }

    public UnityEngine.Object GetAssetFromCurrentAssetBundle(string assetname)
    {
        if (currentAssetbundle != null)
        {
            return currentAssetbundle.LoadAsset(assetname);
        }
        return null;
    }

    public void OnPackageChange()
    {

        RefreshItemList(() =>
        {
            if (appConfigData.packageConfig.assetType == AssetType.SuperAssetBundle)
            {
                CreateNewCardWithSuperBundle(cardbundleName);
            }
            else
            {
                NextIndexItem();
            }

            //列表刷新完成
            EventBus.Instance.BroadCastEvent(EventID.On_Paper_RefreshFinished);
        });
    }

    private void RefreshItemList(Action onfinished)
    {
        shower_items.Clear();
        appConfigData = AppDataManager.Instance.GetCurrentPackageInfo();
        if (appConfigData.packageConfig.assetType == AssetType.AssetBundle)
        {
            string bundlePath = Path.Combine(new string[] { appConfigData.packageDir, "assets", "bundle" });
            StartCoroutine(Res.LoadAssetBundle(bundlePath, (assetbundle) =>
            {
                currentAssetbundle = assetbundle;
                string[] assetlist = assetbundle.GetAllAssetNames();
                if (assetlist.Length > 0)
                {
                    for (int i = 0; i < assetlist.Length; i++)
                    {
                        string item = assetlist[i];
                        if (item.EndsWith(".png") && !item.StartsWith("__"))
                        {
                            shower_items.Add(item);
                        }
                    }
                }

                if (onfinished != null) onfinished();

            }));
        }
        else if (appConfigData.packageConfig.assetType == AssetType.SuperAssetBundle)
        {
            string bundlePath = Path.Combine(new string[] { appConfigData.packageDir, "assets", "bundle" });
            StartCoroutine(Res.LoadAssetBundle(bundlePath, (assetbundle) =>
            {
                currentAssetbundle = assetbundle;

                if (onfinished != null) onfinished();

            }));
        }
        else if (appConfigData.packageConfig.assetType == AssetType.Spine)
        {
            assetdir = Path.Combine(appConfigData.packageDir, "assets");

            if (string.IsNullOrEmpty(assetdir))
            {
                print("图片文件夹不存在");
                assetdir = Application.streamingAssetsPath;
            }

            if (Directory.Exists(assetdir))
            {
                string[] files = Directory.GetFiles(assetdir);
                if (files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].EndsWith(".meta"))
                            continue;
                        shower_items.Add(files[i]);
                    }
                }
            }

            if (onfinished != null) onfinished();
        }
        else
        {
            assetdir = Path.Combine(appConfigData.packageDir, "assets");

            if (string.IsNullOrEmpty(assetdir))
            {
                print("图片文件夹不存在");
                assetdir = Application.streamingAssetsPath;
            }

            if (Directory.Exists(assetdir))
            {
                string[] files = Directory.GetFiles(assetdir);
                if (files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        string item = files[i];
                        if (item.EndsWith(".png") ||
                            item.EndsWith(".mp4") ||
                            item.EndsWith(".gif"))
                        {
                            shower_items.Add(item);
                        }
                    }
                }
            }

            if (onfinished != null) onfinished();

        }
    }

    private void NextItemChangeMode()
    {
        int changeModeIndex = (int)(changeMode) + 1;
        if (changeModeIndex >= (int)ItemChangeMode.Max)
        {
            changeModeIndex = 0;
        }
        appConfigData.packageConfig.changeMode = changeMode = (ItemChangeMode)changeModeIndex;
        AppManager.Instance.Tip = "浏览模式：" + changeMode.ToString();
    }

    void Update()
    {

        appConfigData = AppDataManager.Instance.GetCurrentPackageInfo();

        timer += Time.deltaTime;
        if (timer > appConfigData.packageConfig.changeDur)
        {
            timer = 0;

            NextItem();
        }

        if (Input.GetKeyDown(KeyCode.N))
        {
            NextIndexItem();
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            RefreshItemList(() => { AppManager.Instance.Tip = "刷新列表成功"; });
        }

        //更新抖音效果
        // if (lastcard != null)
        // {
        //     if (appConfigData.packageConfig.isEnableDouYin)
        //     {
        //         (lastcard as CardBase).OnUpdateAmp(EffectMgr.Instance.ProcessMusic.AudioAmp * appConfigData.packageConfig.audioVisulStrengh * 0.4f);
        //     }
        //     else
        //     {
        //         (lastcard as CardBase).OnUpdateAmp(0);
        //     }
        // }
    }

    public void NextItem()
    {
        switch (appConfigData.packageConfig.changeMode)
        {
            case ItemChangeMode.Sequence:
                NextIndexItem();
                break;
            case ItemChangeMode.Random:
                NextRandomItem();
                break;
            default:
                break;
        }
    }

    private void NextIndexItem()
    {
        current_shower_index++;
        if (current_shower_index >= shower_items.Count)
        {
            current_shower_index = 0;
        }
        ChangeImageOrVideo(current_shower_index);
    }

    private void NextRandomItem()
    {
        current_shower_index = Random.Range(0, shower_items.Count);
        ChangeImageOrVideo(current_shower_index);
    }

    Component lastcard;
    private void ChangeImageOrVideo(int currentindex)
    {
        //释放资源
        Resources.UnloadUnusedAssets();

        //决定卡片类型
        string mediaPath = shower_items[currentindex];
        //普通资源
        if (appConfigData.packageConfig.assetType == AssetType.MediaAssets)
        {
            if (mediaPath.EndsWith(".gif"))
            {
                cardtype = CardType.SimpleGifCard;
            }
            else
            {
                //sprite类型时设置特殊的fade类型
                if (appConfigData.packageConfig.checkMode == CheckMode.Accurate)
                {
                    cardtype = CardType.AcurrateCollisionCard;
                    appConfigData.packageConfig.fadeInType = FadeInType.SimpleSpriteIn;
                    appConfigData.packageConfig.fadeOutType = FadeOutType.SimpleSpriteOut;
                }
                else
                {
                    cardtype = CardType.SimpleCard;
                }
            }

            //过渡
            string prefabname = cardtype.ToString();
            if (lastcard == null)
            {
                CreateNewCard(prefabname, mediaPath);
            }
            else
            {
                AppendFadeOutComponent(appConfigData.packageConfig.fadeOutType);

                CreateNewCard(prefabname, mediaPath);

            }
        }
        //assetbundle
        else if (appConfigData.packageConfig.assetType == AssetType.AssetBundle)
        {
            if (lastcard == null)
            {
                CreateNewCardWithBundle(mediaPath);
            }
            else
            {
                AppendFadeOutComponent(appConfigData.packageConfig.fadeOutType);
                CreateNewCardWithBundle(mediaPath);
            }
        }
        else if (appConfigData.packageConfig.assetType == AssetType.Spine)
        {
            cardtype = CardType.SimpleSpineCard;
            CreateNewCardWithSpine(mediaPath);
        }
    }

    private void CreateNewCardWithSpine(string assetname)
    {
        //销毁lastcard
        if (lastcard != null)
        {
            Destroy(lastcard.gameObject);
        }

        Res.LoadGameObjectAsync("Prefabs/cards/" + cardtype.ToString(), (obj) =>
        {
            GameObject newObj = Instantiate<GameObject>(obj, transform);
            Transform temptrans = newObj.transform;
            temptrans.position = anchor1.position;

            CardBase card = temptrans.GetComponent<CardBase>();
            card.imagePath = assetname;

            // AppendFadeInComponent(temptrans, appConfigData.packageConfig.fadeInType);

            lastcard = card;

        });
    }

    //自定义
    private void CreateNewCardWithBundle(string assetname)
    {
        //Debug.Log(assetname);
        UnityEngine.Object cardObj = GetAssetFromCurrentAssetBundle(cardbundleName);
        GameObject newObj = Instantiate<GameObject>(cardObj as GameObject, transform);
        Transform temptrans = newObj.transform;
        temptrans.position = anchor1.position;

        CardBase card = temptrans.GetComponent<CardBase>();
        card.imagePath = assetname;

        AppendFadeInComponent(temptrans, appConfigData.packageConfig.fadeInType);


        if (currentAssetbundle != null)
        {
            currentAssetbundle.Unload(false);
        }

        lastcard = card;
    }

    //超级自定义
    private void CreateNewCardWithSuperBundle(string assetname)
    {
        //释放资源
        Resources.UnloadUnusedAssets();
        //销毁lastcard
        if (lastcard != null)
        {
            EventBus.Instance.BroadCastEvent<EffectMgr.EffectType>(EventID.EffectChangeEvent, EffectMgr.EffectType.none);
            Destroy(lastcard.gameObject);
        }

        Debug.Log(assetname);
        UnityEngine.Object cardObj = GetAssetFromCurrentAssetBundle(cardbundleName);
        GameObject newObj = Instantiate<GameObject>(cardObj as GameObject, transform);
        Transform temptrans = newObj.transform;
        //temptrans.position = anchor1.position;

        TextAsset textAsset = GetAssetFromCurrentAssetBundle("dll.txt") as TextAsset;
        byte[] bytes = textAsset.bytes;
        //Debug.Log(obj.GetType());
        Assembly assembly = Assembly.Load(bytes);
        //经测试这里只能使用AddComponent，lastcard才不会为空
        lastcard = newObj.AddComponent(assembly.GetType("CardMono"));


        if (currentAssetbundle != null)
        {
            currentAssetbundle.Unload(false);
        }
    }

    //普通卡片
    private void CreateNewCard(string prefabname, string imgPath)
    {
        Res.LoadGameObjectAsync("Prefabs/cards/" + prefabname, (obj) =>
        {

            GameObject newObj = Instantiate<GameObject>(obj, transform);
            Transform temptrans = newObj.transform;
            temptrans.position = anchor1.position;

            CardBase card = temptrans.GetComponent<CardBase>();
            card.imagePath = imgPath;

            AppendFadeInComponent(temptrans, appConfigData.packageConfig.fadeInType);

            lastcard = card;

        });
    }

    private void AppendFadeOutComponent(FadeOutType fadetype)
    {
        switch (fadetype)
        {
            case FadeOutType.SimpleAlphaFade:
                lastcard.gameObject.AddComponent<SimpleAlphaFadeOut>();
                break;
            case FadeOutType.SimpleFlyOut:
                lastcard.gameObject.AddComponent<SimpleFlyOut>();
                break;
            case FadeOutType.SimpleSpriteOut:
                lastcard.gameObject.AddComponent<SimpleSpriteOut>();
                break;
            case FadeOutType.Random:
                AppendFadeOutComponent((FadeOutType)(Random.Range(0, (int)FadeOutType.Random)));
                break;
            case FadeOutType.Max:
                break;
            default:
                break;
        }
    }

    private void AppendFadeInComponent(Transform temptrans, FadeInType fadetype)
    {
        switch (fadetype)
        {
            case FadeInType.SimpleAlphaFade:
                temptrans.AddComponentEx<SimpleAlphaFadeIn>();
                break;
            case FadeInType.SimpleFlyIn:
                temptrans.AddComponentEx<SimpleFlyIn>();
                break;
            case FadeInType.SimpleSpriteIn:
                temptrans.AddComponentEx<SimpleSpriteFadeIn>();
                break;
            case FadeInType.Random:
                AppendFadeInComponent(temptrans, (FadeInType)(Random.Range(0, (int)FadeInType.Random)));
                break;
            case FadeInType.Max:
                break;
            default:
                break;
        }
    }
}
